package com.tiny.tinyweb.core.dao.xaccess;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import org.springframework.jdbc.core.ColumnMapRowMapper;

import com.tiny.tinyweb.core.dao.entity.MapEntity;
import com.tiny.tinyweb.core.exception.DaoException;
import com.tiny.tinyweb.core.utils.ConversionUtils;

/**
 * 基于{@link org.springframework.jdbc.core.ColumnMapRowMapper}的映射器类。将结果集映射到具体的实体对象中。
 * @param <T> 实体类的泛型约束
 * @see {@link JdbcXAccess#jdbcRead(String, Map, Class)}
 * @author wxiaobin
 */
public class MapMapper<T extends MapEntity> extends ColumnMapRowMapper {
    /**
     * 映射结果集的具体实体对象。
     */
    private Class<T> entityClass;

    /**
     * 用来指定映射结果集的具体实体对象的构造器。
     */
    public MapMapper(Class<T> entityClass) {
        super();
        this.entityClass = entityClass;
    }

    /**
     * 将结果集映射到具体的实体对象或{@link java.util.Map}对象。
     * @param rs 结果集
     * @param rowNum 数据集的行索引
     * @return 映射后的实体对象或{@link java.util.Map}对象
     * @see {@link org.springframework.jdbc.core.ColumnMapRowMapper#mapRow(ResultSet, int)}
     */
    @Override
    public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
        // 执行父类的mapRow方法，获得映射后的Map对象
        Map<String, Object> row = super.mapRow(rs, rowNum);
        // 如果没有指定想要映射的具体实体类，直接返回父类方法返回的Map对象
        if (this.entityClass == null) {
            return row;
        }
        // 根据具体的映射实体类生成映射后的实体对象
        try {
            MapEntity entity = this.entityClass.newInstance();
            for (String key : row.keySet()) {
            	entity.put(ConversionUtils.camelName(key), row.get(key));
            }
            return entity;
        } catch (Exception e) {
            throw new DaoException("This entity class is not inherited from MapEntity.");
        }
    }
}
